package com.example.yilanchatserver.business.freechat;

import com.alibaba.fastjson.JSONObject;
import com.example.yilanchatserver.business.freechat.service.RedisService;
import com.example.yilanchatserver.business.freechat.service.dto.FreeChatDTO;
import com.example.yilanchatserver.business.freechat.service.dto.FreeChatPromptDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.WebClientResponseException;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.*;

@Slf4j
@Component
public class ZhiPuWebClient {

    private WebClient webClient;

    @Resource
    private RedisService redisService;

    @Value("${wudao.url.stream}")
    private String CHAT_API;

    @Value("${wudao.url.knowledge.chat}")
    private String knowledgeChat;

    @Value("${wudao.url.knowledge.sse}")
    private String knowledgeSSE;

    @Value("${wudao.url.knowledge.baseline}")
    private String knowledgeBase;

    /**
     * dev采用代理访问
     */
    @PostConstruct
    public void init() {
        initProd();
    }





    public void initProd() {
        log.info("initProd");
        this.webClient = WebClient.builder()
                .defaultHeader(HttpHeaders.CONTENT_TYPE, "application/json")
                .build();
    }


    public Flux<String> getChatResponse(FreeChatDTO freeChatDTO, String authToken, Integer maxTokens, Double temperature, Double topP, String talkUUid) {

        JSONObject talkerParams = new JSONObject();
        talkerParams.put("temperature", temperature);
        talkerParams.put("top_p", topP);
        String preUuid = UUID.randomUUID().toString();
        talkerParams.put("requestTaskNo",preUuid);

//        System.out.println(preUuid);


        // 预先设置


        List<Map<String, String>> qaPairs = new ArrayList<>();

        Map<String, String> tmp = new HashMap<>();
        tmp.put("role", "user");
        tmp.put("content", "你是元宇宙展厅的一位数字人员工，现在对你要求如下：\n1.需要在科技展厅面对用户的问题给出严肃、简洁、准确的回答，同时满足用户的闲聊需求，如讲笑话，讲故事等。\n2.如果你确实不知道，也请如实给出不知道的原因，并婉转地表达不知道的意思。\n请扮演上述角色。如果明白，请回答“明白”，无需回答其他信息。");
        qaPairs.add(tmp);
        tmp = new HashMap<>();
        tmp.put("role", "assistant");
        tmp.put("content", "明白。");
        qaPairs.add(tmp);
        if(freeChatDTO.getUserAccount() != null) {
            String prefix = freeChatDTO.getProduct() + ":" + freeChatDTO.getCurrentVirtual() + ":";
            log.info("触发多轮对话，存储信息");
            String userAccount = freeChatDTO.getUserAccount();
            // 存在原先的对话列表
            if(redisService.hasKey(prefix + userAccount)){
                List<String> uuidList = redisService.range(prefix + userAccount);
                int i = 0;
                if(uuidList.size() - 3 > 0) {
                    i = uuidList.size() - 3;
                }
                List<String> newList = uuidList.subList(i, uuidList.size());
                for (String uuid : newList) {
                    List<String> content;
                    if (redisService.hasKey(uuid)) {
                        content = redisService.range(uuid);
                    } else {
                        // 对话已过期，移除索引
                        redisService.deleteElement(prefix + userAccount, uuid);
                        continue;
                    }
                    if(content.size() < 2) {
                        continue;
                    }
                    tmp = new HashMap<>();
                    tmp.put("role", "user");
                    tmp.put("content", content.get(0));
                    qaPairs.add(tmp);
                    tmp = new HashMap<>();
                    tmp.put("role", "assistant");
                    tmp.put("content", content.get(1));
                    qaPairs.add(tmp);

                }
                // 添加索引
            }
            log.info("存入本次对话UUID：" + talkUUid);
            redisService.rpush(prefix + userAccount, talkUUid);
        }


//        if(freeChatDTO.getPrompt() != null){
//            for(int i = 0;i < freeChatDTO.getPrompt().size();i++){
//
//                Map<String, String> tmp =  freeChatDTO.getPrompt().get(i);
//                if(Objects.equals(tmp.get("talker"), "bot")){
//                    tmp.put("talker", "assistant");
//                }
//                tmp.put("role", tmp.remove("talker"));
//                tmp.put("content", tmp.remove("text"));
//                qaPairs.add(tmp);
//            }
//        }

        List<String> storeForRedis = new ArrayList<>();

        for(int i = 0;i < freeChatDTO.getTalkList().size();i++){

            tmp =  freeChatDTO.getTalkList().get(i);
            if(Objects.equals(tmp.get("talker"), "bot")){
                tmp.put("talker", "assistant");
            }
            tmp.put("role", tmp.remove("talker"));
            String text = tmp.remove("text");
            tmp.put("content", text);
            storeForRedis.add(text);
            qaPairs.add(tmp);
        }



        talkerParams.put("prompt", qaPairs);
        System.out.println(preUuid);
        if(!freeChatDTO.getIsKnowledgeable()) {
            log.info("无需情感问答");
            if(freeChatDTO.getUserAccount() != null) {
                String userAccount = freeChatDTO.getUserAccount();
                redisService.rpush(talkUUid, storeForRedis);
            }
            log.info("请求信息为："+(talkerParams.toString()));

            return webClient.post()
                    .uri(CHAT_API)
                    .header(HttpHeaders.AUTHORIZATION, "Bearer " + authToken)
                    .bodyValue(talkerParams.toJSONString())
                    .retrieve()
                    .bodyToFlux(String.class)
                    .onErrorResume(WebClientResponseException.class, ex -> {
                        HttpStatus status = ex.getStatusCode();
                        String res = ex.getResponseBodyAsString();
                        if(freeChatDTO.getUserAccount() != null) {
                            String userAccount = freeChatDTO.getUserAccount();
                            String prefix = freeChatDTO.getProduct() + ":" + freeChatDTO.getCurrentVirtual() + ":";
                            if(redisService.hasKey(prefix + userAccount)){
                                redisService.deleteElement(prefix + userAccount, talkUUid);
                            }
                        }
                        log.error("OpenAI API error: {} {}", status, res);
                        return Mono.error(new RuntimeException(res));
                    });
        }
        else{
            talkerParams.remove("top_p");
            talkerParams.remove("temperature");
            talkerParams.put("incremental", true); // 全量返回
            talkerParams.remove("requestTaskNo");
            qaPairs.remove(0);
            qaPairs.remove(0);
            talkerParams.put("prompt", qaPairs);
            log.info("检测到knowledgeRoleId");
            log.info("调用地址："+knowledgeBase+knowledgeChat+freeChatDTO.getRobotId()+knowledgeSSE);
            log.info("请求信息为："+(talkerParams.toString()));
            return webClient.post()
                    .uri(knowledgeBase+knowledgeChat+freeChatDTO.getRobotId()+knowledgeSSE)
                    .header(HttpHeaders.AUTHORIZATION, "Bearer " + authToken)
                    .bodyValue(talkerParams.toJSONString())
                    .retrieve()
                    .bodyToFlux(String.class)
                    .onErrorResume(WebClientResponseException.class, ex -> {
                        HttpStatus status = ex.getStatusCode();
                        String res = ex.getResponseBodyAsString();
                        log.error("OpenAI API error: {} {}", status, res);
                        return Mono.error(new RuntimeException(res));
                    });
        }

    }

}
